package classDemo;

import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Ajie
 * @date 2022/6/9
 * @function
 */
public class ClassLoader_Test {
    static class ClassHolder {
        public ClassHolder() {
            System.out.println("ClassHolder:ClassHolder:static class 构造函数");
        }
        public static MyClass holder = new MyClass();//属性 执行了1次
    }

    public static void main(String[] args) throws Exception {
        ClassLoader classLoader = Thread.currentThread().getClass().getClassLoader();
        System.out.println("ClassLoader_Test:main:"+(classLoader == null));//true
        //MyClassloader myCl = new MyClassloader(ClassLoader.getSystemClassLoader(), "/Users/macpro/ideaWorkSpace/MyJava/out/production/MyJava");
        MyClassloader myCl = new MyClassloader(ClassLoader.getSystemClassLoader(),"/Users/macpro/ideaWorkSpace/MyJava/out/production/MyJava");
//        MyClassloader.testClassLoader(myCl);

//        Class<?> aClass = myCl.loadClass("classDemo.MyClass");
//        MyClass myClass = (MyClass) aClass.newInstance();
//        myClass.setName("1");
//        System.out.println("ClassLoader_Test:main:"+myClass.getName());


        System.out.println("ClassLoader_Test:main:+ClassHolder.class.getName():"+ClassHolder.class.getName());
//        Class<?> c1 = myCl.loadClass(ClassHolder.class.getName());
        Class<?> c1 = myCl.loadClass("classDemo.ClassLoader_Test$ClassHolder");
        ClassHolder ch = (ClassHolder) c1.newInstance();
        MyClass holder = ch.holder;

        System.out.println("ClassLoader_Test:main:"+ch+"--"+holder);//MyClass@4517d9a3

        MyClassloader myC2 = new MyClassloader(ClassLoader.getSystemClassLoader(),"/Users/macpro/ideaWorkSpace/MyJava/out/production/MyJava");
//        Class<?> c2 = myC2.loadClass(ClassHolder.class.getName());
        Class<?> c2 = myC2.loadClass("classDemo.ClassLoader_Test$ClassHolder");
        ClassHolder ch2 = (ClassHolder) c2.newInstance();
        MyClass holder2 = ch2.holder;

        System.out.println("ClassLoader_Test:main:"+ch2+"--"+holder2);//MyClass@4517d9a3 相同
    }
}

class MyClassloader extends ClassLoader {

    private final String fileSuffix = ".class";
    private final String classLocation;

    public MyClassloader(String classLocation) {
        super();
        this.classLocation = classLocation;
    }

    public MyClassloader(ClassLoader parentClassLoader, String classLocation) {
        super(parentClassLoader);
        this.classLocation = classLocation;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] classData = loadClassData(name);
        return defineClass(name, classData, 0, classData.length);
    }

    private byte[] loadClassData(String name) {
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        byte[] data = null;
        try {
            is = new FileInputStream(new File(classLocation + "/"+name.replace(".", "//") + fileSuffix));
            baos = new ByteArrayOutputStream();
            int r = 0;
            while (-1 != (r = is.read())) {
                baos.write(r);
            }
            is.close();
            baos.close();
            data = baos.toByteArray();
        } catch (Exception ex) {
            Logger.getLogger(MyClassloader.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                is.close();
                baos.close();
            } catch (IOException exx) {
                Logger.getLogger(MyClassloader.class.getName()).log(Level.SEVERE, null, exx);
            }
        }
        return data;
    }

    @Override
    public String toString() {
        return "This is MyClassLoader:" + this.getClass().getSimpleName();
    }

//    public static void main(String[] args) throws Exception {
//        MyClassloader myCl = new MyClassloader(ClassLoader.getSystemClassLoader(), "D:\\NetBeansProjects\\tools\\target\\classes\\");
//        testClassLoader(myCl);
//    }

    static void testClassLoader(MyClassloader cl) throws Exception {
        Class<?> clazz = cl.findClass("classDemo.MyClass");
        System.out.println(clazz.getClassLoader().toString());

        Object newObj = clazz.newInstance();
        System.out.println(newObj);
    }
}


/**
 * @author dangxk
 */



